﻿using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microformats.Enums;
using System.Globalization;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System;

namespace Microformats.Controls
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:hCard runat=server></{0}:hCard>")]
    [PersistChildren(false)]
    [ParseChildren(ChildrenAsProperties = true)]
    public class hCard : WebControl
    {
        public hCard()
        {
            Properties = new Collection<CardProperty>();
        }

        /// <summary>
        /// Gets or sets the tele communication.
        /// </summary>
        /// <value>The tele communication.</value>
        [Browsable(true)]
        [Editor(typeof(CollectionEditor), typeof(UITypeEditor))]
        [Category("Behavior")]
        [Description("Properties")]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Collection<CardProperty> Properties
        {
            get
            {
                object o = ViewState["Properties"];
                return o != null ? (Collection<CardProperty>)o : new Collection<CardProperty>();
            }
            set
            {
                ViewState["Properties"] = value;
            }
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            foreach (CardProperty cardProperty in Properties)
            {
                if (cardProperty is NameCollection)
                {
                    RenderName(ref writer, (NameCollection)cardProperty);
                }
                else if (cardProperty is TeleCommunicationCollection)
                {
                    RenderTeleCommunication(ref writer, (TeleCommunicationCollection)cardProperty);
                }
                else if (cardProperty is CompanyCollection)
                {
                    RenderCompany(ref writer, (CompanyCollection)cardProperty);
                }
                else if (cardProperty is CardGeo)
                {
                    CardGeo geo = cardProperty as CardGeo;

                    geo.Render(ref writer);
                }
                else if (cardProperty is MessagingCollection)
                {
                    MessagingCollection messaging = cardProperty as MessagingCollection;

                    messaging.Render(ref writer);
                }
                else if (cardProperty is Entity)
                {
                    Entity entity = cardProperty as Entity;

                    if (entity is CardAddresses)
                    {
                        RenderAddress(ref writer, (CardAddresses)entity);
                    }
                }
            }

            base.RenderContents(writer);
        }

        private void RenderName(ref HtmlTextWriter writer, NameCollection collection)
        {
            foreach (Name name in collection.Names)
            {
                // Preferred Name
                if (name.PreferredName)
                {
                    name.ClassName = string.Format("fn {0}", name.ClassName);
                }
                
                // Contains Url
                if (!string.IsNullOrEmpty(name.Url))
                {
                    // Add Wrapper Tag
                    writer.RenderBeginTag(name.HtmlTag);

                    name.ClassName = string.Format("url {0}", name.ClassName);

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, name.ClassName);
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, name.Url);
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                }
                else
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Class, name.ClassName);
                    writer.RenderBeginTag(name.HtmlTag);
                }

                writer.WriteLine();
                writer.Indent++;

                // Render Name Properties
                foreach (NameProperty nameProperty in name.NamePropertyCollection)
                {
                    name.ClassName = string.Empty;

                    switch (nameProperty.Type)
                    {
                        case NameTypes.HonorificPrefix:
                            name.ClassName = "honorific-prefix";
                            break;
                        case NameTypes.GivenName:
                            name.ClassName = "given-name";
                            break;
                        case NameTypes.AdditionalName:
                            name.ClassName = "additional-name";
                            break;
                        case NameTypes.FamilyName:
                            name.ClassName = "family-name";
                            break;
                        case NameTypes.HonorificSuffix:
                            name.ClassName = "honorific-suffix";
                            break;
                        default:
                            break;
                    }

                    // Sort This Name Property
                    if (nameProperty.SortString)
                    {
                        name.ClassName = string.Format("{0} sort-string", name.ClassName);
                    }

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, name.ClassName);
                    writer.RenderBeginTag(HtmlTextWriterTag.Span);
                    writer.Write(nameProperty.Value);
                    writer.RenderEndTag();
                    writer.WriteLine();
                }

                // Contains Url
                if (!string.IsNullOrEmpty(name.Url))
                {
                    writer.RenderEndTag();
                }

                writer.Indent--;
                writer.RenderEndTag();
                writer.WriteLine();
            }
        }
        private void RenderCompany(ref HtmlTextWriter writer, CompanyCollection collection)
        {
            foreach (Company company in collection.Companies)
            {
                writer.WriteLine();

                // Contains Url
                if (!string.IsNullOrEmpty(company.Url))
                {
                    // Add Wrapper Tag
                    writer.RenderBeginTag(company.HtmlTag);

                    // Preferred Name
                    if (company.PreferredName)
                    {
                        company.ClassName = string.Format("fn {0}", company.ClassName);
                    }

                    company.ClassName = string.Format("url {0}", company.ClassName);

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, company.ClassName);
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, company.Url);
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                }
                else
                {
                    // Preferred Name
                    if (company.PreferredName)
                    {
                        company.ClassName = string.Format("fn {0}", company.ClassName);
                    }

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, company.ClassName);
                    writer.RenderBeginTag(company.HtmlTag);
                }


                if (string.IsNullOrEmpty(company.Unit))
                {
                    writer.Write(company.Name);
                }
                else
                {
                    writer.WriteLine();
                    writer.Indent++;

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, "organization-name");
                    writer.RenderBeginTag(company.HtmlTag);
                    writer.Write(company.Name);
                    writer.RenderEndTag();
                    writer.Write(", ");
                    writer.AddAttribute(HtmlTextWriterAttribute.Class, "organization-unit");
                    writer.RenderBeginTag(company.HtmlTag);
                    writer.Write(company.Unit);
                    writer.RenderEndTag();

                    writer.Indent--;
                    writer.WriteLine();
                }

                // Contains Url
                if (!string.IsNullOrEmpty(company.Url))
                {
                    writer.RenderEndTag();
                }

                RenderAddress(ref writer, company.AddressCollection);

                writer.RenderEndTag();
                writer.WriteLine();
            }
        }
        private void RenderAddress(ref HtmlTextWriter writer, CardAddresses collection)
        {
            foreach (Address address in collection.Addresses)
            {
                address.Render(ref writer);
            }
        }
        private void RenderTeleCommunication(ref HtmlTextWriter writer, TeleCommunicationCollection collection)
        {
            foreach (TeleCommunication teleCommunication in collection.TeleCommunications)
            {
                writer.WriteLine();

                // Get Container Class Name
                string className = teleCommunication.ClassName;

                if (teleCommunication.Preferred)
                {
                    className = string.Format("{0} pref", className);
                }

                writer.AddAttribute(HtmlTextWriterAttribute.Class, className);
                writer.RenderBeginTag(teleCommunication.HtmlTag);

                if (teleCommunication is Telephone)
                {
                    Telephone telephone = teleCommunication as Telephone;

                    if (telephone != null)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "type");
                        writer.RenderBeginTag(HtmlTextWriterTag.Span);

                        switch (telephone.Type)
                        {
                            case TelephoneType.Home:
                                writer.Write("home");
                                break;
                            case TelephoneType.Message:
                                writer.Write("msg");
                                break;
                            case TelephoneType.Work:
                                writer.Write("work");
                                break;
                            case TelephoneType.Preferred:
                                writer.Write("pref");
                                break;
                            case TelephoneType.Fax:
                                writer.Write("fax");
                                break;
                            case TelephoneType.Cell:
                                writer.Write("cell");
                                break;
                            case TelephoneType.Video:
                                writer.Write("video");
                                break;
                            case TelephoneType.Pager:
                                writer.Write("pager");
                                break;
                            case TelephoneType.BBS:
                                writer.Write("bbs");
                                break;
                            case TelephoneType.Modem:
                                writer.Write("modem");
                                break;
                            case TelephoneType.ISDN:
                                writer.Write("isdn");
                                break;
                            case TelephoneType.PCS:
                                writer.Write("pcs");
                                break;
                            default:
                                writer.Write("voice");
                                break;
                        }

                        writer.RenderEndTag();
                        writer.Write(": ");

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "value");
                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.Write(teleCommunication.Value);
                        writer.RenderEndTag();
                    }
                }
                else if (teleCommunication is Email)
                {
                    Email email = teleCommunication as Email;

                    if (email.Type != EmailType.None)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "type");
                        writer.RenderBeginTag(HtmlTextWriterTag.Span);

                        switch (email.Type)
                        {
                            case EmailType.Internet:
                                writer.Write("internet");
                                break;
                            case EmailType.X400:
                                writer.Write("x400");
                                break;
                            case EmailType.Preferred:
                                writer.Write("pref");
                                break;
                            default:
                                break;
                        }


                        writer.RenderEndTag();
                        writer.Write(": ");
                    }

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, "value");
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, string.Format("mailto:{0}", teleCommunication.Value));
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                    writer.Write(teleCommunication.Value);
                    writer.RenderEndTag();
                }
                else if (teleCommunication is Mailer)
                {
                    Mailer mailer = teleCommunication as Mailer;
                    writer.Write(teleCommunication.Value);
                }

                writer.RenderEndTag();
            }
        }

        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "vcard");

            base.RenderBeginTag(writer);
        }

        public override void RenderEndTag(HtmlTextWriter writer)
        {
            base.RenderEndTag(writer);
        }

        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }
    }
}
